import java.io.*;
import java.net.InetAddress;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;
import java.util.Date;
/**
 *
 * @author Alejandro
 */
public class ServidorR extends UnicastRemoteObject implements IServidorRemoto {

    // <editor-fold defaultstate="collapsed" desc="Variables">

    private int puerto = 0;
    private String ip;
    private String url;
    private String url2;
    private int puerto2;
    private IServidorRemoto obj = null;
    private String respuesta= "";
    private Boolean respuestaBoolean = true;

    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Constructores">

    /**
     * Constructor que Inicializa los Datos de Ip, Puerto y URL
     * @throws RemoteException
     */
    public ServidorR() throws RemoteException
    {
        super();
        puerto = 9998;
        puerto2 = 9999;
        ip = "localhost";
        url = "//" + ip + ":" + puerto + "/ServidorA";
        url2 = "//" + ip + ":" + puerto2 + "/Servidor";
    }

    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Implementacion de IServidorRemoto">

    /**
     * Metodo encargado de enviar la peticion al Servidor de Archivo para que
     * devuelva el contenido de un archivo
     * @param ipCliente: quien hace la peticion
     * @param archivo: archivo que se desea consultar
     * @return: regresa el contenido del archivo
     */
    public String vista(String ipCliente, String archivo){

        try{

            obj = (IServidorRemoto) Naming.lookup(url);
            respuesta = (String)obj.vista(ipCliente, archivo);

            this.escribirBitacora(ipCliente, "vista", "Exitoso: Ver Bitacora del Servidor de Archivos");

            return respuesta;

        }catch (Exception e) {

            this.escribirBitacora(ipCliente, "vista", "Error en Vista");

            return "Error de Vista";
        }
        
    }

    /**
     * Metodo encargado de enviar la Solicitud al Servidor de Archivo de
     * Actualizacion de un archivo
     * @param ipCliente: quien lo pide
     * @param archivo: archivo a actualizar
     * @param informacion: datos que seran agregados al archivo
     * @return: regresa si la operacion fue o no exitosa
     */
    public Boolean actualizar (String ipCliente, String archivo, String informacion){

         try{

            obj = (IServidorRemoto) Naming.lookup(url);
            respuestaBoolean = (Boolean)obj.actualizar(ipCliente, archivo, informacion);

            this.escribirBitacora(ipCliente, "actualizar", "Ver Bitacora del Servidor de Archivos");

            return respuestaBoolean;

        }catch (Exception e) {

            this.escribirBitacora(ipCliente, "actualizar", "Error en Actualizacion");
            respuestaBoolean = false;

            return respuestaBoolean;
        }

    }

    /**
     * Metodo encargado de enviar la Solicitud al Servidor de Archivo para
     * que elimine un archivo determinado
     * @param ipCliente: quien hace la peticion
     * @param archivo: archivo que sera eliminado
     * @return: regresa si la operacion fue exitosa o no
     */
    public Boolean eliminarArchivo (String ipCliente, String archivo){

        try{

            obj = (IServidorRemoto) Naming.lookup(url);
            respuestaBoolean = (Boolean)obj.eliminarArchivo(ipCliente, archivo);

            this.escribirBitacora(ipCliente, "eliminar", "Ver Bitacora del Servidor de Archivos");

            return respuestaBoolean;

        }catch (Exception e) {

            this.escribirBitacora(ipCliente, "eliminar", "Error en Actualizacion");
            respuestaBoolean = false;

            return respuestaBoolean;
        }

    }

    /**
     * Metodo que se encarga de devolver el contenido de la bitacora de
     * cualquiera de los servidores
     * @param ipCliente: para ubicar el Cliente que hizo la operacion
     * @param servidor: para verificar si es con el servidor RMI o de Archivos
     * @return: regresa un string con todo el contenido de la bitacora
     */
    public String consultarBitacora (String ipCliente, String servidor){

        try{

            if (servidor.compareTo("archivo") == 0){

                obj = (IServidorRemoto) Naming.lookup(url);
                respuesta = (String)obj.consultarBitacora(ipCliente, servidor);

            }
            else{

                try{
                    
                    FileReader fichero = new FileReader("BitacoraRMI.txt");
                    BufferedReader lector = new BufferedReader(fichero);

                    while(lector.ready()){
                    
                        respuesta = respuesta + lector.readLine() + "\n";

                    }

                    fichero.close();

                }catch (Exception e) {
                    e.printStackTrace();
                }

            }
            
            this.escribirBitacora(ipCliente, "consultar Bitacora", "Bitacora del Servidor de Solicitudes Consultada");

            return respuesta;

        }catch (Exception e) {

            this.escribirBitacora(ipCliente, "consultar Bitacora", "Error en Consulta de Bitacora");
            respuesta = "Error en Consulta de Bitacora";

            return respuesta;
        }
        
    }

    /**
     * Metodo que devuelve una lista con los archivos y sus pesos en KB
     * @param ipCliente: quien hace la peticion
     * @return: lista de archivos
     */
    public String[][] listaArchivos(String ipCliente){

        String[][] respuestaLista = null;

        try{

            obj = (IServidorRemoto) Naming.lookup(url);
            respuestaLista = (String[][])obj.listaArchivos(ipCliente);

            this.escribirBitacora(ipCliente, "lista de Archivos", "Ver Bitacora del Servidor de Archivos");

            return respuestaLista;

        }catch (Exception e) {

            this.escribirBitacora(ipCliente, "lista de Archivos", "Error al listar los Archivos");

            return respuestaLista;
        }
        
    }

    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Metodos Propios">

    /**
     * Metodo que levanta el Servidor para que sea accesible a los clientes
     * @return: regresa si el levantamiento fue exitoso o no
     */
    public boolean registrarServicio(){

        try
        {
            // crea el RMIRegistry en el puerto indicado
            LocateRegistry.createRegistry(puerto2);
            Naming.bind("//" + InetAddress.getLocalHost().getHostAddress() +":" + puerto2 + "/Servidor", this);
            System.out.println("Servidor de Archivos ha sido iniciado exitosamente");
            return true;
         }
         catch (Exception e)
         {
            System.out.println("Error al iniciar servidor, causa: " + e.toString());
            return false;
         }
    }

    /**
     * Metodo encargado de escribir las acciones que se van haciendo en la bitacora
     * @param ipCliente: quien mando a hacer la peticion
     * @param accion: la accion que realizo, ej: eliminar
     * @param comentario: breves palabras que se diran de la accion
     */
    public void escribirBitacora(String ipCliente, String accion, String comentario){
        
        try{
            FileWriter ficheroR = new FileWriter("BitacoraRMI.txt",true);
            PrintWriter escritor = new PrintWriter(ficheroR);

            Date fechaActual = new Date();
            escritor.println(ipCliente + " - " + accion + " - " +fechaActual.toString() + " - " + comentario);

            escritor.close();
            ficheroR.close();


        }catch (Exception e) {
            e.printStackTrace();
        }

    }

    // </editor-fold>

    public static void main(String[] args) throws RemoteException
    {

        try
        {
            ServidorR server = new ServidorR();
            if (!server.registrarServicio())
                System.exit(1);
        }
        catch (Exception e)
        {
            System.out.println(e);
        }
    }

}
